﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using System.Reflection;
using System.Globalization;
using System.Data;
using System.Collections;
using System.IO;
using System.Web;
using System.Xml;
using System.Text.RegularExpressions;
using Newtonsoft.Json;
using Mammoo.Xml;

namespace Mammoo.Ajax
{

    /// <summary>
    /// Copyright (C) 2009 Augustus.Xiong
    /// 版权所有
    ///  
    /// 文件名：       JsonHelp
    /// 文件功能描述： json辅助类库
    /// 
    /// 创建标识：     Augustus.Xiong 2008-10-10
    /// 
    /// 
    /// </summary>
    public abstract class JsonHelper
    {
        #region WriteObject
        /// <summary>
        /// 写DataRow
        /// </summary>
        /// <param name="sb"></param>
        /// <param name="row"></param>
        private static void WriteDataRow(StringBuilder sb, DataRow row)
        {
            sb.Append("{");
            foreach (DataColumn column in row.Table.Columns)
            {
                sb.AppendFormat("\"{0}\":", column.ColumnName);
                WriteValue(sb, row[column]);
                sb.Append(",");
            }
            // Remove the trailing comma.
            if (row.Table.Columns.Count > 0)
            {
                --sb.Length;
            }
            sb.Append("}");
        }

        /// <summary>
        /// 写DataSet
        /// </summary>
        /// <param name="sb"></param>
        /// <param name="ds"></param>
        private static void WriteDataSet(StringBuilder sb, DataSet ds)
        {
            //sb.Append("{\"Tables\":{");
            foreach (DataTable table in ds.Tables)
            {
                // sb.AppendFormat("\"{0}\":", table.TableName);
                WriteDataTable(sb, table);
                sb.Append(",");
            }
            // Remove the trailing comma.
            if (ds.Tables.Count > 0)
            {
                --sb.Length;
            }
            // sb.Append("}}");
        }

        /// <summary>
        /// 写DataTable
        /// </summary>
        /// <param name="sb"></param>
        /// <param name="table"></param>
        private static void WriteDataTable(StringBuilder sb, DataTable table)
        {
            sb.Append("[");
            foreach (DataRow row in table.Rows)
            {
                WriteDataRow(sb, row);
                sb.Append(",");
            }
            // Remove the trailing comma.
            if (table.Rows.Count > 0)
            {
                --sb.Length;
            }
            sb.Append("]");
        }

        /// <summary>
        /// 写元素
        /// </summary>
        /// <param name="sb"></param>
        /// <param name="e"></param>
        private static void WriteEnumerable(StringBuilder sb, IEnumerable e)
        {
            bool hasItems = false;
            sb.Append("[");
            foreach (object val in e)
            {
                WriteValue(sb, val);
                sb.Append(",");
                hasItems = true;
            }
            // Remove the trailing comma.
            if (hasItems)
            {
                --sb.Length;
            }
            sb.Append("]");
        }

        /// <summary>
        /// 写Hash表
        /// </summary>
        /// <param name="sb"></param>
        /// <param name="e"></param>
        private static void WriteHashtable(StringBuilder sb, Hashtable e)
        {
            bool hasItems = false;
            sb.Append("{");
            foreach (string key in e.Keys)
            {
                sb.AppendFormat("\"{0}\":", key.ToLower());
                WriteValue(sb, e[key]);
                sb.Append(",");
                hasItems = true;
            }
            // Remove the trailing comma.
            if (hasItems)
            {
                --sb.Length;
            }
            sb.Append("}");
        }

        /// <summary>
        /// 写对象
        /// </summary>
        /// <param name="sb"></param>
        /// <param name="o"></param>
        private static void WriteObject(StringBuilder sb, object o)
        {
            MemberInfo[] members = o.GetType().GetMembers(BindingFlags.Instance | BindingFlags.Public);
            sb.Append("{");
            bool hasMembers = false;
            foreach (MemberInfo member in members)
            {
                bool hasValue = false;
                object val = null;
                if ((member.MemberType & MemberTypes.Field) == MemberTypes.Field)
                {
                    FieldInfo field = (FieldInfo)member;
                    val = field.GetValue(o);
                    hasValue = true;
                }
                else if ((member.MemberType & MemberTypes.Property) == MemberTypes.Property)
                {
                    PropertyInfo property = (PropertyInfo)member;
                    if (property.CanRead && property.GetIndexParameters().Length == 0)
                    {
                        val = property.GetValue(o, null);
                        hasValue = true;
                    }
                }
                if (hasValue)
                {
                    sb.Append("\"");
                    sb.Append(member.Name);
                    sb.Append("\":");
                    WriteValue(sb, val);
                    sb.Append(",");
                    hasMembers = true;
                }
            }
            if (hasMembers)
            {
                --sb.Length;
            }
            sb.Append("}");
        }

        /// <summary>
        /// 写字符串
        /// </summary>
        /// <param name="sb"></param>
        /// <param name="s"></param>
        private static void WriteString(StringBuilder sb, string s)
        {
            sb.Append("\"");
            foreach (char c in s)
            {
                switch (c)
                {
                    case '\"':
                        sb.Append("\\\"");
                        break;
                    case '\\':
                        sb.Append("\\\\");
                        break;
                    case '\b':
                        sb.Append("\\b");
                        break;
                    case '\f':
                        sb.Append("\\f");
                        break;
                    case '\n':
                        sb.Append("\\n");
                        break;
                    case '\r':
                        sb.Append("\\r");
                        break;
                    case '\t':
                        sb.Append("\\t");
                        break;
                    default:
                        int i = (int)c;
                        if (i < 32 || i > 127)
                        {
                            sb.AppendFormat("\\u{0:X04}", i);
                        }
                        else
                        {
                            sb.Append(c);
                        }
                        break;
                }
            }
            sb.Append("\"");
        }

        /// <summary>
        /// 写值
        /// </summary>
        /// <param name="sb"></param>
        /// <param name="val"></param>
        private static void WriteValue(StringBuilder sb, object val)
        {
            if (val == null || val == System.DBNull.Value)
            {
                sb.Append("null");
            }
            else if (val is string || val is Guid)
            {
                WriteString(sb, val.ToString());
            }
            else if (val is bool)
            {
                sb.Append(val.ToString().ToLower());
            }
            else if (val is double ||
                val is float ||
                val is long ||
                val is int ||
                val is short ||
                val is byte ||
                val is decimal)
            {
                sb.AppendFormat(CultureInfo.InvariantCulture.NumberFormat, "{0}", val);
            }
            else if (val.GetType().IsEnum)
            {
                sb.Append((int)val);
            }
            else if (val is DateTime)
            {
                sb.Append("\"");
                sb.Append(((DateTime)val).ToString("yyyy-MM-dd HH:mm:ss", new CultureInfo("en-US", false).DateTimeFormat));
                sb.Append("\"");
            }
            else if (val is DataSet)
            {
                WriteDataSet(sb, val as DataSet);
            }
            else if (val is DataTable)
            {
                WriteDataTable(sb, val as DataTable);
            }
            else if (val is DataRow)
            {
                WriteDataRow(sb, val as DataRow);
            }
            else if (val is Hashtable)
            {
                WriteHashtable(sb, val as Hashtable);
            }
            else if (val is IEnumerable)
            {
                WriteEnumerable(sb, val as IEnumerable);
            }
            else if (val is StringBuilder)
            {
                sb.Append(val.ToString());
            }
            else
            {
                WriteObject(sb, val);
            }
        }
        #endregion



        #region JsonConvert

        #region Convert2Json
        /// <summary>
        /// 将object转化成Json格式
        /// </summary>
        /// <param name="o">object对象</param>
        /// <returns>string</returns>
        public static string Convert2Json(object o)
        {
            return Convert2Json(o, "");
        }

        /// <summary>
        /// 将object转化成Json格式
        /// </summary>
        /// <param name="o">object对象</param>
        /// <param name="noConvertKeys">不需要转换的key</param>
        /// <returns></returns>
        public static string Convert2Json(object o, string noConvertKeys)
        {
            StringBuilder sb = new StringBuilder();
            if (o is Hashtable)
            {
                return Convert2Json((Hashtable)o, noConvertKeys);
            }
            else
            {
                WriteValue(sb, o);
            }
            return sb.ToString();
        }

        /// <summary>
        /// 转Json
        /// </summary>
        /// <param name="ht">Hashtable</param>
        /// <returns></returns>
        public static string Convert2Json(Hashtable ht)
        {
            return Convert2Json(ht, "");
        }

        /// <summary>
        /// 转Json
        /// </summary>
        /// <param name="ht">Hashtable</param>
        /// <param name="noConvertKeys">不用Convert2Json的值，用,分割</param>
        /// <returns></returns>
        public static string Convert2Json(Hashtable ht, string noConvertKeys)
        {
            StringBuilder sb = new StringBuilder();
            noConvertKeys = "," + noConvertKeys + ",";
            sb.Append("{");
            foreach (object key in ht.Keys)
            {
                if (noConvertKeys.IndexOf("," + key.ToString() + ",") != -1)
                {
                    sb.AppendFormat("{0}:{1},", Convert2Json(key), ht[key]);
                }
                else
                {
                    sb.AppendFormat("{0}:{1},", Convert2Json(key), Convert2Json(ht[key]));
                }
            }

            if (sb.Length > 1)
            {
                --sb.Length;
            }
            sb.Append("}");
            return sb.ToString();
        }
        #endregion

        #region Convert2JsonMap
        /// <summary>
        /// 转JsonMap
        /// </summary>
        /// <param name="drList"></param>
        /// <param name="keyField"></param>
        /// <param name="prix"></param>
        /// <returns></returns>
        public static StringBuilder Convert2JsonMap(DataRow[] drList, string keyField, string prix)
        {
            Hashtable ht = new Hashtable();
            foreach (DataRow dr in drList)
            {
                ht.Add(string.Format("{0}{1}", prix, dr[keyField]), dr);
            }
            return new StringBuilder(Convert2Json(ht));
        }

        /// <summary>
        /// 转JsonMap
        /// </summary>
        /// <param name="drList"></param>
        /// <param name="keyField"></param>
        /// <param name="prix"></param>
        /// <returns></returns>
        public static StringBuilder Convert2JsonMap(List<DataRow> drList, string keyField, string prix)
        {
            return Convert2JsonMap(drList.ToArray(), keyField, prix);
        }

        /// <summary>
        /// 转JsonMap
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="keyField"></param>
        /// <param name="prix"></param>
        /// <returns></returns>
        public static StringBuilder Convert2JsonMap(DataTable dt, string keyField, string prix)
        {
            return new StringBuilder(Convert2JsonMap(dt.Select("1=1"), keyField, prix).ToString());
        }

        /// <summary>
        /// 转JsonMap
        /// </summary>
        /// <param name="ds"></param>
        /// <param name="keyField"></param>
        /// <param name="prix"></param>
        /// <returns></returns>
        public static StringBuilder Convert2JsonMap(DataSet ds, string keyField, string prix)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("[");
            foreach (DataTable dt in ds.Tables)
            {
                sb.Append(Convert2JsonMap(ds.Tables[0], keyField, prix).ToString() + ",");
            }
            if (sb.Length > 1)
            {
                --sb.Length;
            }
            sb.Append("]");
            return sb;
        }
        #endregion

        #region Convert2JsonMapList
        /// <summary>
        ///  转JsonMapList
        /// </summary>
        /// <param name="drList"></param>
        /// <param name="keyField"></param>
        /// <param name="prix"></param>
        /// <returns></returns>
        public static StringBuilder Convert2JsonMapList(DataRow[] drList, string keyField, string prix)
        {
            Hashtable ht = new Hashtable();
            foreach (DataRow dr in drList)
            {
                if (!ht.ContainsKey(string.Format("{0}{1}", prix, dr[keyField])))
                {
                    ht.Add(string.Format("{0}{1}", prix, dr[keyField]), new List<DataRow>());
                }
                ((List<DataRow>)ht[string.Format("{0}{1}", prix, dr[keyField])]).Add(dr);
            }
            return new StringBuilder(Convert2Json(ht));
        }

        /// <summary>
        /// 转JsonMapList
        /// </summary>
        /// <param name="drList"></param>
        /// <param name="keyField"></param>
        /// <param name="prix"></param>
        /// <returns></returns>
        public static StringBuilder Convert2JsonMapList(List<DataRow> drList, string keyField, string prix)
        {
            return Convert2JsonMapList(drList.ToArray(), keyField, prix);
        }

        /// <summary>
        /// 转JsonMapList
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="keyField"></param>
        /// <param name="prix"></param>
        /// <returns></returns>
        public static StringBuilder Convert2JsonMapList(DataTable dt, string keyField, string prix)
        {
            return Convert2JsonMapList(dt.Select("1=1"), keyField, prix);
        }
        /// <summary>
        /// 转JsonMapList
        /// </summary>
        /// <param name="ds"></param>
        /// <param name="keyField"></param>
        /// <param name="prix"></param>
        /// <returns></returns>
        public static StringBuilder Convert2JsonMapList(DataSet ds, string keyField, string prix)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("[");
            foreach (DataTable dt in ds.Tables)
            {
                sb.Append(Convert2JsonMapList(dt, keyField, prix) + ",");
            }
            if (sb.Length > 1)
            {
                --sb.Length;
            }
            sb.Append("]");
            return sb;
        }
        #endregion

        #region ConvertToTreeJson
        /// <summary>
        /// 从datatable生成tree的json数据源
        /// </summary>
        /// <param name="dt">数据源datatable</param>
        /// <param name="idField">指定表的id列名</param>
        /// <param name="fatherField">fatherid列名</param>
        /// <param name="fatherID">fatherid的值</param>
        /// <returns></returns>
        public static string ConvertToTreeJson(DataTable dt, string idField, string fatherField, int fatherID)
        {
            StringBuilder sb = new StringBuilder();
            bool b = false;
            foreach (DataRow row in dt.Select(string.Format(fatherField + "= {0}", fatherID)))
            {
                sb.Append("{");

                if (dt.Select(string.Format(fatherField + "= {0}", row[idField])).Length != 0)
                {
                    b = true;
                }
                else
                {
                    b = false;
                }
                foreach (DataColumn column in dt.Columns)
                {
                    sb.Append(column.ColumnName + ":'" + row[column].ToString() + "'");
                    if ((!column.Equals(dt.Columns[dt.Columns.Count - 1])) || b)
                    {
                        sb.Append(",");
                    }
                    else
                    {
                        sb.Append(",leaf:true");
                    }
                }
                if (b)
                {
                    sb.Append("children:[");
                    sb.Append(ConvertToTreeJson(dt, idField, fatherField, Convert.ToInt32(row[idField])));
                    sb.Append("]");
                }
                sb.Append("}");
                if ((!row.Equals(dt.Select(string.Format(fatherField + "= {0}", fatherID))[dt.Select(string.Format(fatherField + "= {0}", fatherID)).Length - 1])))
                {
                    sb.Append(",");
                }
            }
            return sb.ToString();
        }

        /// <summary>
        /// 转换成树
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="idField"></param>
        /// <param name="fatherField"></param>
        /// <param name="fatherID"></param>
        /// <param name="checkedField"></param>
        /// <param name="checkedValue"></param>
        /// <returns></returns>
        public static string ConvertToTreeJson(DataTable dt, string idField, string fatherField, int fatherID, string checkedField, int checkedValue)
        {
            StringBuilder sb = new StringBuilder();
            bool b = false;
            foreach (DataRow row in dt.Select(string.Format(fatherField + "= {0}", fatherID)))
            {
                sb.Append("{");
                if (row[checkedField].ToString() == checkedValue.ToString())
                {
                    sb.Append("  checked:true, ");
                }

                if (dt.Select(string.Format(fatherField + "= {0}", row[idField])).Length != 0)
                {
                    b = true;
                }
                else
                {
                    b = false;
                }
                foreach (DataColumn column in dt.Columns)
                {
                    sb.Append(column.ColumnName + ":'" + row[column].ToString() + "'");
                    if ((!column.Equals(dt.Columns[dt.Columns.Count - 1])) || b)
                    {
                        sb.Append(",");
                    }
                    else
                    {
                        sb.Append(",leaf:true");
                    }
                }
                if (b)
                {
                    sb.Append("children:[");
                    sb.Append(ConvertToTreeJson(dt, idField, fatherField, Convert.ToInt32(row[idField]), checkedField, checkedValue));
                    sb.Append("]");
                }
                sb.Append("}");
                if ((!row.Equals(dt.Select(string.Format(fatherField + "= {0}", fatherID))[dt.Select(string.Format(fatherField + "= {0}", fatherID)).Length - 1])))
                {
                    sb.Append(",");
                }
            }
            return sb.ToString();
        }

        /// <summary>
        /// 转换成树
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        public static string ConvertToTreeJson(XmlNode node)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("{");
            sb.Append(string.Format("id:'{0}',", node.SelectSingleNode("id").InnerText));
            sb.Append(string.Format("text:'{0}',", node.SelectSingleNode("text").InnerText));
            sb.Append(string.Format("href:'{0}',", node.SelectSingleNode("href").InnerText));
            sb.Append(string.Format("icon:'{0}',", node.SelectSingleNode("icon").InnerText));

            if (node.SelectNodes("children").Count > 0)
            {
                sb.Append("children:[");
                foreach (XmlNode childrenNode in node.SelectNodes("children"))
                {
                    sb.Append(ConvertToTreeJson(childrenNode));
                }
                sb.Remove(sb.Length - 1, 1);
                sb.Append("]");
            }
            else
            {
                sb.Append(string.Format("leaf:{0}", node.SelectSingleNode("leaf").InnerText));
            }
            sb.Append("},");

            return sb.ToString();
        }
        #endregion

        /// <summary>
        /// 将Json字符串转换成object
        /// </summary>
        /// <param name="value">Json字符串</param>
        /// <param name="type">要转换成的类型,typeof(目标对象)</param>
        /// <returns>Object</returns>
        public static object Convert2Entity(string value, Type type)
        {
            return JavaScriptConvert.DeserializeObject(value, type);
        }

        public static Hashtable Convert2Hashtable(string value)
        {
            Hashtable ht = new Hashtable();
            if (string.IsNullOrEmpty(value))
            {
                return ht;
            }

            if (!value.StartsWith("{") || !value.EndsWith("}"))
            {
                throw new Exception("Error Json Format");
            }
            value = value.Remove(0, 1);
            value = value.Remove(value.Length - 1, 1);
            if (value.Length > 0)
            {
                string[] json = value.Split(',');
                foreach (string j in json)
                {
                    var item = j.Split(':');
                    if (item.Length == 2)
                    {
                        if (item[1].StartsWith("\"") && item[1].EndsWith("\""))
                        {
                            ht.Add(item[0], item[1].Substring(1, item[1].Length - 2));
                        }
                        else if (item[1].StartsWith("'") && item[1].EndsWith("'"))
                        {
                            ht.Add(item[0], item[1].Substring(1, item[1].Length - 2));
                        }
                        else
                        {
                            ht.Add(item[0], item[1]);
                        }
                    }
                    else
                    {
                        throw new Exception("Error Json Format");
                    }
                }
            }
            return ht;
        }

        /// <summary>
        /// 将Json字符串转换成XML节点
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static XmlNode Convert2Xml(string value)
        {
            return JavaScriptConvert.DeerializeXmlNode(value);
        }

        /// <summary>
        /// 获取页面表单项内容
        /// </summary>
        /// <param name="json">表单集合</param>
        /// <param name="pname">表单项名称</param>
        /// <returns></returns>
        public static string FormReader(string json, string pname)
        {
            string strReturn = "";
            string strMatch = @"'" + pname + "':'(?<pname>.*?)'";
            if (json != null && json != "")
            {
                Regex objRegex = new Regex(strMatch, RegexOptions.IgnoreCase | RegexOptions.Multiline);
                if (objRegex.IsMatch(json))
                {

                    Match objMatch = objRegex.Match(json);
                    strReturn = objMatch.Groups["pname"].ToString();
                }
                if (strReturn != "")
                {
                    strReturn = HttpContext.Current.Server.UrlDecode(strReturn);
                }
            }
            return strReturn;
        }

        /// <summary>
        /// 创建列
        /// </summary>
        /// <param name="xmlPath">xml路径</param>
        /// <returns></returns>
        private static string CreateColumn(string xmlPath)
        {
            XmlHelper Doc = new XmlHelper(HttpContext.Current.Server.MapPath(xmlPath));
            XmlNodeList NodeList = Doc.GetList("//Column");
            StringBuilder Sb = new StringBuilder();
            foreach (XmlNode node in NodeList)
            {
                Sb.Append("{");
                foreach (XmlNode nd in node.ChildNodes)
                {
                    Sb.Append(nd.Name + ":" + nd.InnerText + ",");
                }
                Sb.Append("},");
            }
            Doc.Dispose();
            Sb = Sb.Replace(",}", "}");
            return Sb.ToString().Remove(Sb.ToString().Length - 1);
        }

        /// <summary>
        /// 写DataTable
        /// </summary>
        /// <param name="table"></param>
        /// <returns></returns>
        public static string WriteDataTable(DataTable table)
        {
            StringBuilder Sb = new StringBuilder();
            Sb.Append("[");
            foreach (DataRow row in table.Rows)
            {
                WriteDataRow(Sb, row);
                Sb.Append(",");
            }
            // Remove the trailing comma.
            if (table.Rows.Count > 0)
            {
                --Sb.Length;
            }
            Sb.Append("]");
            return Sb.ToString();

        }
        #endregion
    }
}
